package com.tos.second.common.handler;

import com.alibaba.fastjson.JSON;
import com.tos.second.entity.ChatMessage;
import com.tos.second.service.ChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {
    
    // 注入ChatService
    @Autowired
    private ChatService chatService;
    
    // 存储用户连接会话
    private static final ConcurrentHashMap<Long, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    
    /**
     * 连接建立后的处理
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId != null) {
            userSessions.put(userId, session);
            // 更新用户在线状态
            chatService.updateUserOnlineStatus(userId, true);
            log.info("用户 {} 已连接，当前在线用户数: {}", userId, userSessions.size());
        }
    }
    
    /**
     * 处理收到的文本消息
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId == null) {
            session.close();
            return;
        }
        
        try {
            // 解析消息
            ChatMessage chatMessage = JSON.parseObject(message.getPayload(), ChatMessage.class);
            chatMessage.setSenderId(userId);
            chatMessage.setCreateTime(LocalDateTime.now());
            chatMessage.setIsRead(0); // 默认未读
            
            // 保存消息到数据库
            chatService.saveMessage(chatMessage);
            
            // 转发消息给接收者
            sendMessageToUser(chatMessage.getReceiverId(), chatMessage);
        } catch (Exception e) {
            log.error("处理消息时发生错误: {}", e.getMessage());
        }
    }
    
    /**
     * 处理连接关闭
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId != null) {
            userSessions.remove(userId);
            // 更新用户在线状态
            chatService.updateUserOnlineStatus(userId, false);
            log.info("用户 {} 断开连接，当前在线用户数: {}", userId, userSessions.size());
        }
    }
    
    /**
     * 处理传输错误
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket传输错误: {}", exception.getMessage());
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId != null) {
            userSessions.remove(userId);
            // 更新用户在线状态
            chatService.updateUserOnlineStatus(userId, false);
        }
        if (session.isOpen()) {
            session.close();
        }
    }
    
    /**
     * 发送消息给指定用户
     * @param userId 用户ID
     * @param message 消息内容
     */
    public static boolean sendMessageToUser(Long userId, ChatMessage message) {
        WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(JSON.toJSONString(message)));
                return true;
            } catch (Exception e) {
                log.error("发送消息给用户 {} 失败: {}", userId, e.getMessage());
            }
        }
        return false;
    }
    
    /**
     * 获取在线用户数
     * @return 在线用户数
     */
    public static int getOnlineUserCount() {
        return userSessions.size();
    }
    
    /**
     * 判断用户是否在线
     * @param userId 用户ID
     * @return 是否在线
     */
    public static boolean isUserOnline(Long userId) {
        return userSessions.containsKey(userId) && userSessions.get(userId).isOpen();
    }
}